home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / prsr_lib / allocate.c next >
Encoding:
C/C++ Source or Header  |  1993-12-30  |  25.5 KB  |  832 lines

  1. /*****************************************************************************
  2. *   Dynamic allocation module of "Irit" - the 3d polygonal solid modeller.   *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Mar. 1990   *
  5. *****************************************************************************/
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "irit_sm.h"
  10. #include "iritprsr.h"
  11. #include "allocate.h"
  12. #include "attribut.h"
  13. #include "imalloc.h"
  14.  
  15. /* #define DEBUG1            Print more messages in free/allocating. */
  16.  
  17. #define ALLOCATE_NUM    100       /* Number of objects to allocate at once. */
  18.  
  19. typedef enum {
  20.     ALLOC_OTHER,
  21.     ALLOC_VERTEX,
  22.     ALLOC_POLYGON,
  23.     ALLOC_OBJECT
  24. } AllocateStructType;
  25.  
  26. /* Used for fast reallocation of most common object types: */
  27. static IPVertexStruct
  28.     *VertexFreedList = NULL;
  29. static IPPolygonStruct
  30.     *PolygonFreedList = NULL;
  31. static IPObjectStruct
  32.     *ObjectFreedList = NULL;
  33.  
  34. static void IPFreeObjectSlots(IPObjectStruct *PObj);
  35. static void ListObjectRealloc(IPObjectStruct *PObj);
  36. static void IPMallocObjectSlots(IPObjectStruct *PObj);
  37.  
  38. /*****************************************************************************
  39. * Routine to free the slots of a given object.                     *
  40. *****************************************************************************/
  41. static void IPFreeObjectSlots(IPObjectStruct *PObj)
  42. {
  43.     int Index;
  44.     char Line[LINE_LEN];
  45.     IPObjectStruct *PObjTmp;
  46.  
  47.     if (PObj == NULL)
  48.     return;
  49.  
  50.     switch (PObj -> ObjType) {
  51.     case IP_OBJ_UNDEF:
  52.         break;
  53.     case IP_OBJ_POLY:           /* Free the polygon list. */
  54.         IPFreePolygonList(PObj -> U.Pl);
  55.         break;
  56.     case IP_OBJ_NUMERIC:
  57.     case IP_OBJ_POINT:
  58.     case IP_OBJ_VECTOR:
  59.     case IP_OBJ_PLANE:
  60.     case IP_OBJ_CTLPT:
  61.         break;
  62.     case IP_OBJ_MATRIX:
  63.         IritFree((VoidPtr) PObj -> U.Mat);
  64.         break;
  65.     case IP_OBJ_STRING:
  66.         IritFree((VoidPtr) PObj -> U.Str);
  67.         break;
  68.     case IP_OBJ_LIST_OBJ: /* Need to dereference list elements. */
  69.         for (Index = 0;
  70.          (PObjTmp = ListObjectGet(PObj, Index)) != NULL;
  71.          Index++) {
  72.         if (PObjTmp -> Count-- == 1)
  73.             IPFreeObject(PObjTmp);
  74.         }
  75.         IritFree((VoidPtr) PObj -> U.Lst.PObjList);
  76.         break;
  77.     case IP_OBJ_CURVE:
  78.         CagdCrvFreeList(PObj -> U.Crvs);
  79.         break;
  80.     case IP_OBJ_SURFACE:
  81.         CagdSrfFreeList(PObj -> U.Srfs);
  82.         break;
  83.     default:         /* Kill the program - something is WRONG! */
  84.         sprintf(Line,
  85.             "IPFree: Attempt to free undefined Object type %d",
  86.                         PObj -> ObjType);
  87.         IritPrsrFatalError(Line);
  88.         break;
  89.     }
  90. }
  91.  
  92. /*****************************************************************************
  93. * Allocate one Vertex Structure:                         *
  94. *****************************************************************************/
  95. IPVertexStruct *IPAllocVertex(ByteType Count, ByteType Tags,
  96.                   IPPolygonStruct *PAdj, IPVertexStruct *Pnext)
  97. {
  98.     IPVertexStruct *p;
  99.  
  100.     if (VertexFreedList != NULL) {
  101.     p = VertexFreedList;
  102.     VertexFreedList = VertexFreedList -> Pnext;
  103.     }
  104.     else {
  105.     int i;
  106.     IPVertexStruct *V;
  107.  
  108.     /* Allocate ALLOCATE_NUM objects, returns first one as new   */
  109.     /* and chain together the rest of them into the free list.   */
  110.     if ((V = (IPVertexStruct *) IritMalloc(sizeof(IPVertexStruct)
  111.                            * ALLOCATE_NUM)) != NULL) {
  112.         for (i = 1; i < ALLOCATE_NUM - 1; i++)
  113.         V[i].Pnext = &V[i+1];
  114.         V[ALLOCATE_NUM-1].Pnext = NULL;
  115.         VertexFreedList = &V[1];
  116.     }
  117.     p = V;
  118.     }
  119.  
  120.     ZAP_MEM(p, sizeof(IPVertexStruct));
  121.     p -> Count = Count;
  122.     p -> Tags = Tags;
  123.     p -> PAdj = PAdj;
  124.     p -> Pnext = Pnext;
  125.  
  126.     AttrResetAttributes(&p -> Attrs);           /* Initialize attributes. */
  127.  
  128.     return p;
  129. }
  130.  
  131. /*****************************************************************************
  132. * Allocate one Polygon Structure:                         *
  133. *****************************************************************************/
  134. IPPolygonStruct *IPAllocPolygon(ByteType Count, ByteType Tags,
  135.                 IPVertexStruct *V, IPPolygonStruct *Pnext)
  136. {
  137.     IPPolygonStruct *p;
  138.  
  139.     if (PolygonFreedList != NULL) {
  140.     p = PolygonFreedList;
  141.     PolygonFreedList = PolygonFreedList -> Pnext;
  142.     }
  143.     else {
  144.     int i;
  145.     IPPolygonStruct *P;
  146.  
  147.     /* Allocate ALLOCATE_NUM objects, returns first one as new   */
  148.     /* and chain together the rest of them into the free list.   */
  149.     if ((P = (IPPolygonStruct *) IritMalloc(sizeof(IPPolygonStruct)
  150.                             * ALLOCATE_NUM)) != NULL) {
  151.         for (i = 1; i < ALLOCATE_NUM - 1; i++)
  152.         P[i].Pnext = &P[i+1];
  153.         P[ALLOCATE_NUM-1].Pnext = NULL;
  154.         PolygonFreedList = &P[1];
  155.     }
  156.     p = P;
  157.     }
  158.  
  159.     ZAP_MEM(p, sizeof(IPPolygonStruct));
  160.     p -> Count = Count;
  161.     p -> Tags = Tags;
  162.     p -> PVertex = V;
  163.     p -> Pnext = Pnext;
  164.  
  165.     AttrResetAttributes(&p -> Attrs);           /* Initialize attributes. */
  166.  
  167.     return p;
  168. }
  169.  
  170. /*****************************************************************************
  171. * Allocate one Object Structure:                         *
  172. *****************************************************************************/
  173. IPObjectStruct *IPAllocObject(char *Name, IPObjStructType ObjType,
  174.                              IPObjectStruct *Pnext)
  175. {
  176.     IPObjectStruct *p;
  177.  
  178.     if (ObjectFreedList != NULL) {
  179.     p = ObjectFreedList;
  180.     ObjectFreedList = ObjectFreedList -> Pnext;
  181.     }
  182.     else {
  183.     int i;
  184.     IPObjectStruct *O;
  185.  
  186.     /* Allocate ALLOCATE_NUM objects, returns first one as new   */
  187.     /* and chain together the rest of them into the free list.   */
  188.     if ((O = (IPObjectStruct *) IritMalloc(sizeof(IPObjectStruct)
  189.                            * ALLOCATE_NUM)) != NULL) {
  190.         for (i = 1; i < ALLOCATE_NUM - 1; i++)
  191.         O[i].Pnext = &O[i+1];
  192.         O[ALLOCATE_NUM - 1].Pnext = NULL;
  193.         ObjectFreedList = &O[1];
  194.     }
  195.     p = O;
  196.     }
  197.  
  198.     ZAP_MEM(p, sizeof(IPObjectStruct));
  199.     strcpy(p -> Name, Name);
  200.     p -> ObjType = ObjType;
  201.     p -> Count = 1;
  202.     p -> Pnext = Pnext;
  203.  
  204.     IPMallocObjectSlots(p);
  205.     AttrResetAttributes(&p -> Attrs);           /* Initialize attributes. */
  206.  
  207.     return p;
  208. }
  209.  
  210. /*****************************************************************************
  211. * Free one Vertex Structure:                             *
  212. *****************************************************************************/
  213. void IPFreeVertex(IPVertexStruct *V)
  214. {
  215.     if (V != NULL) {
  216.     V ->Pnext = NULL;
  217.     IPFreeVertexList(V);
  218.     }
  219. }
  220.  
  221. /*****************************************************************************
  222. * Free one Polygon Structure:                             *
  223. *****************************************************************************/
  224. void IPFreePolygon(IPPolygonStruct *P)
  225. {
  226.     if (P != NULL) {
  227.     P -> Pnext = NULL;
  228.     IPFreePolygonList(P);
  229.     }
  230. }
  231.  
  232. /*****************************************************************************
  233. * Free one Object Structure:                             *
  234. *****************************************************************************/
  235. void IPFreeObject(IPObjectStruct *O)
  236. {
  237.     if (O != NULL) {
  238.     if (O -> Count > 1) {
  239.         /* Do not free object - just decrease its reference count. */
  240.         O -> Count--;
  241.     }
  242.     else {
  243.         AttrFreeAttributes(&O -> Attrs);
  244.         IPFreeObjectSlots(O);
  245.  
  246.         /* Add it to global freed object list: */
  247.         O -> Pnext = ObjectFreedList;
  248.         ObjectFreedList = O;
  249.     }
  250.     }
  251. }
  252.  
  253. /*****************************************************************************
  254. * Free a (circular) Vertex Structure list.                     *
  255. *****************************************************************************/
  256. void IPFreeVertexList(IPVertexStruct *VFirst)
  257. {
  258.     if (VFirst != NULL) {
  259.     IPVertexStruct *Vtemp,
  260.         *V = VFirst;
  261.  
  262.     /* Handle both circular or NULL terminated. */
  263.     do {
  264.         Vtemp = V;
  265.         V = V -> Pnext;
  266.     }
  267.     while (V != NULL && V != VFirst);
  268.  
  269.     /* Now chain this new list to the global freed vertex list: */
  270.     Vtemp -> Pnext = VertexFreedList;
  271.     VertexFreedList = VFirst;
  272.     }
  273. }
  274.  
  275. /*****************************************************************************
  276. * Free a Polygon Structure list.                         *
  277. *****************************************************************************/
  278. void IPFreePolygonList(IPPolygonStruct *PFirst)
  279. {
  280.     if (PFirst != NULL) {
  281.     IPPolygonStruct
  282.         *Ptemp = NULL,
  283.         *P = PFirst;
  284.  
  285.     while (P != NULL) {
  286.         IPFreeVertexList(P -> PVertex);
  287.  
  288.         Ptemp = P;
  289.         P = P -> Pnext;
  290.     }
  291.  
  292.     /* Now chain this new list to the global freed polygon list: */
  293.     Ptemp -> Pnext = PolygonFreedList;
  294.     PolygonFreedList = PFirst;
  295.     }
  296. }
  297.  
  298. /*****************************************************************************
  299. * Free an Object Structure list.                         *
  300. *****************************************************************************/
  301. void IPFreeObjectList(IPObjectStruct *OFirst)
  302. {
  303.     while (OFirst != NULL) {
  304.     IPObjectStruct
  305.         *NextO = OFirst -> Pnext;
  306.  
  307.     IPFreeObject(OFirst);
  308.     OFirst = NextO;
  309.     }
  310. }
  311.  
  312. /*****************************************************************************
  313. * Returns the length of a list, given a list object.                 *
  314. *****************************************************************************/
  315. int ListObjectLength(IPObjectStruct *PObj)
  316. {
  317.     int i;
  318.     IPObjectStruct **PObjList;
  319.  
  320.     if (!IP_IS_OLST_OBJ(PObj))
  321.     IritPrsrFatalError("List object expected");
  322.  
  323.     for (i = 0, PObjList = PObj -> U.Lst.PObjList; *PObjList++ != NULL; i++)
  324.     if (i >= PObj -> U.Lst.ListMaxLen)
  325.         break;
  326.  
  327.     return i;
  328. }
  329.  
  330. /*****************************************************************************
  331. * Insert an object at index Index into list object.                 *
  332. *****************************************************************************/
  333. void ListObjectInsert(IPObjectStruct *PObj, int Index,
  334.                              IPObjectStruct *PObjItem)
  335. {
  336.     if (!IP_IS_OLST_OBJ(PObj))
  337.     IritPrsrFatalError("List object expected");
  338.  
  339.     if (PObj -> U.Lst.ListMaxLen <= Index)
  340.     ListObjectRealloc(PObj);
  341.  
  342.     PObj -> U.Lst.PObjList[Index] = PObjItem;
  343. }
  344.  
  345. /*****************************************************************************
  346. * Returns the Index object in list of PObjList object.                 *
  347. *****************************************************************************/
  348. IPObjectStruct *ListObjectGet(IPObjectStruct *PObj, int Index)
  349. {
  350.     if (!IP_IS_OLST_OBJ(PObj))
  351.     IritPrsrFatalError("List object expected");
  352.  
  353.     return PObj -> U.Lst.ListMaxLen > Index ? PObj -> U.Lst.PObjList[Index]
  354.                         : NULL;
  355. }
  356.  
  357. /*****************************************************************************
  358. * Reallocate a list Object to twice the list size:                 *
  359. *****************************************************************************/
  360. static void ListObjectRealloc(IPObjectStruct *PObj)
  361. {
  362.     IPObjectStruct
  363.     **PObjList = IritMalloc(sizeof(IPObjectStruct *) *
  364.                 PObj -> U.Lst.ListMaxLen * 2);
  365.  
  366.     GEN_COPY(PObjList, PObj -> U.Lst.PObjList,
  367.          PObj -> U.Lst.ListMaxLen * sizeof(IPObjectStruct *));
  368.     PObj -> U.Lst.ListMaxLen *= 2;
  369.     IritFree((VoidPtr) PObj -> U.Lst.PObjList);
  370.     PObj -> U.Lst.PObjList = PObjList;
  371. }
  372.  
  373. /*****************************************************************************
  374. * Routine to (m)allocate the slots of a given object.                 *
  375. *****************************************************************************/
  376. static void IPMallocObjectSlots(IPObjectStruct *PObj)
  377. {
  378.     switch (PObj -> ObjType) {
  379.     case IP_OBJ_MATRIX:
  380.         PObj -> U.Mat = (MatrixType *) IritMalloc(sizeof(MatrixType));
  381.         break;
  382.     case IP_OBJ_STRING:
  383.         PObj -> U.Str = (char *) IritMalloc(LINE_LEN);
  384.         PObj -> U.Str[0] = 0;
  385.         break;
  386.     case IP_OBJ_LIST_OBJ:
  387.         PObj -> U.Lst.PObjList = (IPObjectStruct **)
  388.         IritMalloc(sizeof(IPObjectStruct *) * MAX_OBJ_LIST);
  389.         PObj -> U.Lst.PObjList[0] = NULL;
  390.         PObj -> U.Lst.ListMaxLen = MAX_OBJ_LIST;
  391.         break;
  392.     default:
  393.         PObj -> U.VPtr = NULL;
  394.         break;
  395.     }
  396. }
  397.  
  398. /*****************************************************************************
  399. *   Generate one polygonal object:                         *
  400. *****************************************************************************/
  401. IPObjectStruct *GenPolyObject(char *Name, IPPolygonStruct *Pl,
  402.                             IPObjectStruct *Pnext)
  403. {
  404.     IPObjectStruct *PObj;
  405.  
  406.     PObj = IPAllocObject(Name, IP_OBJ_POLY, Pnext);
  407.     IP_SET_POLYGON_OBJ(PObj);           /* Default - not polyline object. */
  408.  
  409.     PObj -> U.Pl = Pl;                 /* Link the union part of it... */
  410.  
  411.     return PObj;
  412. }
  413.  
  414. /*****************************************************************************
  415. *   Generate one polygonal object (wrapper):                     *
  416. *****************************************************************************/
  417. IPObjectStruct *GenPOLYObject(IPPolygonStruct *Pl)
  418. {
  419.     return GenPolyObject("", Pl, NULL);
  420. }
  421.  
  422. /*****************************************************************************
  423. *   Generate one curve object:                             *
  424. *****************************************************************************/
  425. IPObjectStruct *GenCrvObject(char *Name, CagdCrvStruct *Crv,
  426.                             IPObjectStruct *Pnext)
  427. {
  428.     IPObjectStruct *PObj;
  429.  
  430.     PObj = IPAllocObject(Name, IP_OBJ_CURVE, Pnext);
  431.  
  432.     PObj -> U.Crvs = Crv;             /* Link the union part of it... */
  433.  
  434.     return PObj;
  435. }
  436.  
  437. /*****************************************************************************
  438. *   Generate one curve object (wrapper):                     *
  439. *****************************************************************************/
  440. IPObjectStruct *GenCRVObject(CagdCrvStruct *Crv)
  441. {
  442.     return GenCrvObject("", Crv, NULL);
  443. }
  444.  
  445. /*****************************************************************************
  446. *   Generate one surface object:                         *
  447. *****************************************************************************/
  448. IPObjectStruct *GenSrfObject(char *Name, CagdSrfStruct *Srf,
  449.                             IPObjectStruct *Pnext)
  450. {
  451.     IPObjectStruct *PObj;
  452.  
  453.     PObj = IPAllocObject(Name, IP_OBJ_SURFACE, Pnext);
  454.  
  455.     PObj -> U.Srfs = Srf;             /* Link the union part of it... */
  456.  
  457.     return PObj;
  458. }
  459.  
  460. /*****************************************************************************
  461. *   Generate one surface object (wrapper):                     *
  462. *****************************************************************************/
  463. IPObjectStruct *GenSRFObject(CagdSrfStruct *Srf)
  464. {
  465.     return GenSrfObject("", Srf, NULL);
  466. }
  467.  
  468. /*****************************************************************************
  469. *   Generate one control point object:                         *
  470. *   Only one of CagdCoords/Coords should be specified.                 *
  471. *****************************************************************************/
  472. IPObjectStruct *GenCtlPtObject(char *Name, CagdPointType PtType,
  473.         CagdRType *CagdCoords, RealType *Coords, IPObjectStruct *Pnext)
  474. {
  475.     int i;
  476.     CagdBType
  477.     IsNotRational = !CAGD_IS_RATIONAL_PT(PtType);
  478.     IPObjectStruct *PObj;
  479.     RealType *t;
  480.  
  481.     PObj = IPAllocObject(Name, IP_OBJ_CTLPT, Pnext);
  482.  
  483.     PObj -> U.CtlPt.PtType = PtType;
  484.     t = PObj -> U.CtlPt.Coords;
  485.  
  486.     if (CagdCoords != NULL)
  487.     for (i = IsNotRational; i <= CAGD_NUM_OF_PT_COORD(PtType); i++)
  488.         t[i] = CagdCoords[i];
  489.     else
  490.     for (i = IsNotRational; i <= CAGD_NUM_OF_PT_COORD(PtType); i++)
  491.         t[i] = Coords[i];
  492.  
  493.     return PObj;
  494. }
  495.  
  496. /*****************************************************************************
  497. *   Generate one control point object (wrapper):                 *
  498. *****************************************************************************/
  499. IPObjectStruct *GenCTLPTObject(CagdPointType PtType, CagdRType *CagdCoords,
  500.                             RealType *Coords)
  501. {
  502.     return GenCtlPtObject("", PtType, CagdCoords, Coords, NULL);
  503. }
  504.  
  505. /*****************************************************************************
  506. *   Generate one numeric object:                         *
  507. *****************************************************************************/
  508. IPObjectStruct *GenNumObject(char *Name, RealType *R, IPObjectStruct *Pnext)
  509. {
  510.     IPObjectStruct *PObj;
  511.  
  512.     PObj = IPAllocObject(Name, IP_OBJ_NUMERIC, Pnext);
  513.  
  514.     PObj -> U.R = *R;                 /* Link the union part of it... */
  515.  
  516.     return PObj;
  517. }
  518.  
  519. /*****************************************************************************
  520. *   Generate one numeric object (wrapper):                     *
  521. *****************************************************************************/
  522. IPObjectStruct *GenNUMObject(RealType *R)
  523. {
  524.     return GenNumObject("", R, NULL);
  525. }
  526.  
  527. /*****************************************************************************
  528. *   Generate one numeric object (wrapper):                     *
  529. *****************************************************************************/
  530. IPObjectStruct *GenNUMValObject(RealType R)
  531. {
  532.     return GenNumObject("", &R, NULL);
  533. }
  534.  
  535. /*****************************************************************************
  536. *   Generate one point object:                             *
  537. *****************************************************************************/
  538. IPObjectStruct *GenPtObject(char *Name, RealType *Pt0, RealType *Pt1,
  539.                     RealType *Pt2, IPObjectStruct *Pnext)
  540. {
  541.     IPObjectStruct *PObj;
  542.  
  543.     PObj = IPAllocObject(Name, IP_OBJ_POINT, Pnext);
  544.  
  545.     PObj -> U.Pt[0] = *Pt0;             /* Link the union part of it... */
  546.     PObj -> U.Pt[1] = *Pt1;
  547.     PObj -> U.Pt[2] = *Pt2;
  548.  
  549.     return PObj;
  550. }
  551.  
  552. /*****************************************************************************
  553. *   Generate one point object (wrapper):                     *
  554. *****************************************************************************/
  555. IPObjectStruct *GenPTObject(RealType *Pt0, RealType *Pt1, RealType *Pt2)
  556. {
  557.     return GenPtObject("", Pt0, Pt1, Pt2, NULL);
  558. }
  559.  
  560. /*****************************************************************************
  561. *   Generate one vector object:                             *
  562. *****************************************************************************/
  563. IPObjectStruct *GenVecObject(char *Name, RealType *Vec0, RealType *Vec1,
  564.                     RealType *Vec2, IPObjectStruct *Pnext)
  565. {
  566.     IPObjectStruct *PObj;
  567.  
  568.     PObj = IPAllocObject(Name, IP_OBJ_VECTOR, Pnext);
  569.  
  570.     PObj -> U.Vec[0] = *Vec0;             /* Link the union part of it... */
  571.     PObj -> U.Vec[1] = *Vec1;
  572.     PObj -> U.Vec[2] = *Vec2;
  573.  
  574.     return PObj;
  575. }
  576.  
  577. /*****************************************************************************
  578. *   Generate one vector object (wrapper):                     *
  579. *****************************************************************************/
  580. IPObjectStruct *GenVECObject(RealType *Vec0, RealType *Vec1, RealType *Vec2)
  581. {
  582.     return GenVecObject("", Vec0, Vec1, Vec2, NULL);
  583. }
  584.  
  585. /*****************************************************************************
  586. *   Generate one plane object:                             *
  587. *****************************************************************************/
  588. IPObjectStruct *GenPlaneObject(char *Name, RealType *Plane0, RealType *Plane1,
  589.               RealType *Plane2, RealType *Plane3, IPObjectStruct *Pnext)
  590. {
  591.     IPObjectStruct *PObj;
  592.  
  593.     PObj = IPAllocObject(Name, IP_OBJ_PLANE, Pnext);
  594.  
  595.     PObj -> U.Plane[0] = *Plane0;        /* Link the union part of it... */
  596.     PObj -> U.Plane[1] = *Plane1;
  597.     PObj -> U.Plane[2] = *Plane2;
  598.     PObj -> U.Plane[3] = *Plane3;
  599.  
  600.     return PObj;
  601. }
  602.  
  603. /*****************************************************************************
  604. *   Generate one plane object (wrapper):                     *
  605. *****************************************************************************/
  606. IPObjectStruct *GenPLANEObject(RealType *Plane0, RealType *Plane1,
  607.                          RealType *Plane2, RealType *Plane3)
  608. {
  609.     return GenPlaneObject("", Plane0, Plane1, Plane2, Plane3, NULL);
  610. }
  611.  
  612. /*****************************************************************************
  613. *   Generate one matrix object:                             *
  614. *****************************************************************************/
  615. IPObjectStruct *GenMatObject(char *Name, MatrixType Mat, IPObjectStruct *Pnext)
  616. {
  617.     int i, j;
  618.     IPObjectStruct *PObj;
  619.  
  620.     PObj = IPAllocObject(Name, IP_OBJ_MATRIX, Pnext);
  621.  
  622.     for (i = 0; i < 4; i++)             /* Link the union part of it... */
  623.     for (j = 0; j < 4; j++)
  624.         (*PObj -> U.Mat)[i][j] = Mat[i][j];
  625.  
  626.     return PObj;
  627. }
  628.  
  629. /*****************************************************************************
  630. *   Generate one matrix object (wrapper):                     *
  631. *****************************************************************************/
  632. IPObjectStruct *GenMATObject(MatrixType Mat)
  633. {
  634.     return GenMatObject("", Mat, NULL);
  635. }
  636.  
  637. /*****************************************************************************
  638. *   Routine to reallocate as necessary and object to a new object type.      *
  639. *****************************************************************************/
  640. void ReallocNewTypeObject(IPObjectStruct *PObj, IPObjStructType ObjType)
  641. {
  642.     if (PObj -> ObjType == ObjType)
  643.         return;
  644.     IPFreeObjectSlots(PObj);
  645.     PObj -> ObjType = ObjType;
  646.     IPMallocObjectSlots(PObj);
  647. }
  648.  
  649. /*****************************************************************************
  650. *   Routine to create a whole new copy of an object Src into Dest.         *
  651. * if Dest is NULL, new object is allocated, otherwise Dest itself is updated *
  652. * If CopyAll then all the record is copied, otherwise, only its variant      *
  653. * element (i.e. no Name/Pnext coping) is been copied.                 *
  654. *****************************************************************************/
  655. IPObjectStruct *CopyObject(IPObjectStruct *Dest, IPObjectStruct *Src,
  656.                                 int CopyAll)
  657. {
  658.     int Index;
  659.     char Line[LINE_LEN];
  660.     IPObjectStruct *PObjTmp;
  661.  
  662.     if (Dest == Src)
  663.     return Dest;            /* Called with same object - ignore. */
  664.     else if (Dest == NULL)
  665.     Dest = IPAllocObject("", Src -> ObjType, NULL);
  666.     else {
  667.     IPFreeObjectSlots(Dest);
  668.     Dest -> ObjType = Src -> ObjType;
  669.     IPMallocObjectSlots(Dest);
  670.     AttrFreeAttributes(&Dest -> Attrs);
  671.     }
  672.  
  673.     if (CopyAll) {
  674.     strcpy(Dest -> Name, Src -> Name);
  675.     Dest -> Pnext = Src -> Pnext;     /* Maybe assigning NULL is better!? */
  676.     }
  677.  
  678.     Dest -> Attrs = AttrCopyAttributes(Src -> Attrs);
  679.  
  680.     switch (Src -> ObjType) {
  681.     case IP_OBJ_UNDEF:
  682.         break;
  683.     case IP_OBJ_POLY:
  684.         Dest -> U.Pl = CopyPolygonList(Src -> U.Pl);
  685.         if (IP_IS_POLYGON_OBJ(Src))
  686.             IP_SET_POLYGON_OBJ(Dest);
  687.         else if (IP_IS_POLYLINE_OBJ(Src))
  688.             IP_SET_POLYLINE_OBJ(Dest);
  689.         else if (IP_IS_POINTLIST_OBJ(Src))
  690.             IP_SET_POINTLIST_OBJ(Dest);
  691.         break;
  692.     case IP_OBJ_NUMERIC:
  693.         Dest -> U.R = Src -> U.R;
  694.         break;
  695.     case IP_OBJ_POINT:
  696.         PT_COPY(Dest -> U.Pt, Src -> U.Pt);
  697.         break;
  698.     case IP_OBJ_VECTOR:
  699.         PT_COPY(Dest -> U.Vec, Src -> U.Vec);
  700.         break;
  701.     case IP_OBJ_PLANE:
  702.         PLANE_COPY(Dest -> U.Plane, Src -> U.Plane);
  703.         break;
  704.     case IP_OBJ_CTLPT:
  705.         GEN_COPY(&Dest -> U.CtlPt, &Src -> U.CtlPt,
  706.              sizeof(CagdCtlPtStruct));
  707.         break;
  708.     case IP_OBJ_MATRIX:
  709.         if (Dest -> U.Mat == NULL)
  710.         Dest -> U.Mat = (MatrixType *) IritMalloc(sizeof(MatrixType));
  711.         MAT_COPY(*Dest -> U.Mat, *Src -> U.Mat);
  712.         break;
  713.     case IP_OBJ_STRING:
  714.         if (Dest -> U.Str == NULL)
  715.         Dest -> U.Str = (char *) IritMalloc(LINE_LEN);
  716.         strcpy(Dest -> U.Str, Src -> U.Str);
  717.         break;
  718.     case IP_OBJ_LIST_OBJ:
  719.         if (Dest -> U.Lst.PObjList != NULL)
  720.         IritFree((VoidPtr) Dest -> U.Lst.PObjList);
  721.         Dest -> U.Lst.PObjList = (IPObjectStruct **)
  722.         IritMalloc(sizeof(IPObjectStruct *) * Src -> U.Lst.ListMaxLen);
  723.         Dest -> U.Lst.ListMaxLen = Src -> U.Lst.ListMaxLen;
  724.  
  725.         GEN_COPY(Dest -> U.Lst.PObjList, Src -> U.Lst.PObjList,
  726.              Dest -> U.Lst.ListMaxLen * sizeof(IPObjectStruct *));
  727.         for (Index = 0;
  728.          (PObjTmp = ListObjectGet(Dest, Index)) != NULL;
  729.          Index++)
  730.         PObjTmp -> Count++;               /* Inc. # of ref. */
  731.         break;
  732.     case IP_OBJ_CURVE:
  733.         Dest -> U.Crvs = CagdCrvCopyList(Src -> U.Crvs);
  734.         break;
  735.     case IP_OBJ_SURFACE:
  736.         Dest -> U.Srfs = CagdSrfCopyList(Src -> U.Srfs);
  737.         break;
  738.     default:
  739.         sprintf(Line,
  740.         "CopyObject Attemp to copy undefined object %s type %d",
  741.         Src -> Name, Src -> ObjType);
  742.         IritPrsrFatalError(Line);
  743.     }
  744.     return Dest;
  745. }
  746.  
  747. /*****************************************************************************
  748. *   Routine to generate a new copy of an object polygon list.             *
  749. *****************************************************************************/
  750. IPObjectStruct *CopyObjectList(IPObjectStruct *PObjs, int CopyAll)
  751. {
  752.     IPObjectStruct *PObj,
  753.     *NewPObjs = NULL,
  754.     *TailPObj =NULL;
  755.  
  756.     for (PObj = PObjs; PObj != NULL; PObj = PObj -> Pnext) {
  757.     if (NewPObjs == NULL)
  758.         NewPObjs = TailPObj = CopyObject(NULL, PObj, CopyAll);
  759.     else {
  760.         TailPObj -> Pnext = CopyObject(NULL, PObj, CopyAll);
  761.         TailPObj = TailPObj -> Pnext;
  762.     }
  763.     }
  764.  
  765.     return NewPObjs;
  766. }
  767.  
  768. /*****************************************************************************
  769. *   Routine to generate a new copy of an object polygon list.             *
  770. *****************************************************************************/
  771. IPPolygonStruct *CopyPolygonList(IPPolygonStruct *Src)
  772. {
  773.     IPPolygonStruct *Phead, *Ptail;
  774.  
  775.     if (Src == NULL)
  776.     return NULL;
  777.  
  778.     /* Prepare the header of the new polygon list: */
  779.     Phead = Ptail = IPAllocPolygon(1, Src -> Tags,
  780.                    CopyVertexList(Src -> PVertex), NULL);
  781.     PLANE_COPY(Ptail -> Plane, Src -> Plane);
  782.     Ptail -> Attrs = AttrCopyAttributes(Src -> Attrs);
  783.     IP_RST_BBOX_POLY(Ptail);
  784.     Src = Src -> Pnext;
  785.  
  786.     while (Src != NULL) {
  787.     Ptail -> Pnext = IPAllocPolygon(Src -> Count, Src -> Tags,
  788.                     CopyVertexList(Src -> PVertex), NULL);
  789.     Ptail = Ptail -> Pnext;
  790.     PLANE_COPY(Ptail -> Plane, Src -> Plane);
  791.     Ptail -> Attrs = AttrCopyAttributes(Src -> Attrs);
  792.     IP_RST_BBOX_POLY(Ptail);
  793.     Src = Src -> Pnext;
  794.     }
  795.  
  796.     return Phead;
  797. }
  798.  
  799. /*****************************************************************************
  800. *   Routine to generate a new copy of a polygon vertices list.             *
  801. *****************************************************************************/
  802. IPVertexStruct *CopyVertexList(IPVertexStruct *Src)
  803. {
  804.     IPVertexStruct *Phead, *Ptail,
  805.     *SrcFirst = Src;
  806.  
  807.     if (Src == NULL)
  808.     return NULL;
  809.  
  810.     /* Prepare the header of the new vertex list: */
  811.     Phead = Ptail = IPAllocVertex(Src -> Count, Src -> Tags, NULL, NULL);
  812.     PT_COPY(Phead -> Coord, Src -> Coord);
  813.     PT_COPY(Phead -> Normal, Src -> Normal);
  814.     Phead -> Attrs = AttrCopyAttributes(Src -> Attrs);
  815.     Src = Src -> Pnext;
  816.  
  817.     while (Src != SrcFirst && Src != NULL) {
  818.     Ptail -> Pnext = IPAllocVertex(Src -> Count, Src -> Tags, NULL, NULL);
  819.     Ptail = Ptail -> Pnext;
  820.     PT_COPY(Ptail -> Coord, Src -> Coord);
  821.     PT_COPY(Ptail -> Normal, Src -> Normal);
  822.     Ptail -> Attrs = AttrCopyAttributes(Src -> Attrs);
  823.  
  824.     Src = Src -> Pnext;
  825.     }
  826.  
  827.     if (Src == SrcFirst)
  828.     Ptail -> Pnext = Phead;               /* Make vertex list circular. */
  829.  
  830.     return Phead;
  831. }
  832.